'''
This example demonstates syncronizing an Analog Output and Input using
the counter.
'''
import nidaqmx as DAQmx
import scipy as sp
import pylab as pl
import time

########################################################################
# Configuration
########################################################################
Fs = 10000.0
nSamples = 1000
os=1 #Read over sampling ratio

#Build some data to output
#stim is a single triangle, but the ends are both 3.3, 
#so we can identify them as the ends and make sure we read them
stim = sp.linspace(0.0, 6.6, num=nSamples)
stim[int(nSamples/2):] = 6.6-stim[int(nSamples/2):]
stim[0]=3.3
stim[-2]=3.3 #stim[-1] will be output as the last point is being read
             #So it will not be read
#nidaqmx will only accept true lists, not numpy arrays
stim = stim.tolist()

#This tasks creates a pulsing output from the counter that will be used
#to trigger the Read & Write
triggerTask = DAQmx.CreateTask("Trigger")
DAQmx.CreateCOPulseChanFreq(triggerTask,"/Dev1/ctr0","",\
            DAQmx.Val_Hz, DAQmx.Val_Low, 0.0, Fs, 0.5)
DAQmx.CfgImplicitTiming(triggerTask,DAQmx.Val_FiniteSamps, 1) #We only need one pulse

#This is the output task
outTask = DAQmx.CreateTask("Stimulate")
DAQmx.CreateAOVoltageChan(outTask,"Dev1/ao0","",0.0,4.0,\
            DAQmx.Val_Volts, None)
DAQmx.CfgSampClkTiming(outTask,"",Fs,DAQmx.Val_Rising,\
            DAQmx.Val_FiniteSamps,nSamples)
#Trigger on the counter. PFI12 is the output of counter 0
DAQmx.CfgDigEdgeStartTrig(outTask,"/Dev1/PFI12",DAQmx.Val_Rising)

#This is the read task
inTask = DAQmx.CreateTask("Read")
DAQmx.CreateAIVoltageChan(inTask,"Dev1/ai0","",\
            DAQmx.Val_RSE ,0.0,4.0,\
            DAQmx.Val_Volts,None)
DAQmx.CfgSampClkTiming(inTask,"",os*Fs,DAQmx.Val_Rising,\
            DAQmx.Val_FiniteSamps,os*nSamples)
#Trigger on the counter. PFI12 is the output of counter 0
DAQmx.CfgDigEdgeStartTrig(inTask,"/Dev1/PFI12",DAQmx.Val_Rising)

########################################################################
# Measurement
########################################################################

#Setup the data that will be output on the trigger
DAQmx.WriteAnalogF64(outTask,nSamples,0,10.0, DAQmx.Val_GroupByChannel,stim)

DAQmx.StartTask(inTask) #This will start on the trigger
time.sleep(0.1) #Just to prove that they are waiting for the trigger, add a delay
DAQmx.StartTask(outTask)#This will start on the trigger

DAQmx.StartTask(triggerTask) #Start the counter and trigger the tasks

#Now retreive the data we read
read = DAQmx.ReadAnalogF64(inTask, os*nSamples, 1.0, \
            DAQmx.Val_GroupByChannel, os*nSamples)

#Clean up the tasks
for t in [inTask, outTask, triggerTask] :
    DAQmx.StopTask(t)
    DAQmx.ClearTask(t)

#and plot the data
t = sp.arange(0,nSamples/Fs, step=1.0/(os*Fs))
pl.plot(t,read,'+-') #We should get a M shaped plot
pl.xlim([-0.01, 0.11])
pl.show()
